#ifndef __STP_H__
#define __STP_H__

#include "stp_proto.h"
#include "stp_timer.h"

#include "base.h"
#include "types.h"

#define STP_MAX_PORTS 32

extern const u8 eth_stp_addr[];

typedef struct stp stp_t;

// 指定端口的判断标准，当前端口所在网段的走向根节点的上一跳（离根节点更近）交换机就是当前端口所在的路由器
// 并且当前端口所在网段走向根节点的上一跳端口就是自己

// 这里是一个交换机中一个端口的元数据，主要包括这个端口认为的根交换机的
// 当然每个交换机端口记录的是这个端口所在网段的stp元数据

// 每个端口发送的信息只有端口id不一样。
struct stp_port {
	stp_t *stp;					// pointer to stp

	int port_id;				// port id
	char *port_name;
	iface_info_t *iface;

	int path_cost;				// cost of this port, always be 1 in this lab

	// 本网段到根节点最小开销配置。

	
	u64 designated_root;		// root switch (the port believes)

	// 当前端口坐在网段到根节点路径上的最近交换机
	u64 designated_switch;		// the switch sending this config

	// 当前端口所在网段到根节点的上一跳端口
	int designated_port;		// the port sending this config，此端口向更远的节点发送消息

	// 当前端口所在网段到根节点的路径开销，不包括数据包通过当前网段的通过开销
	int designated_cost;		// path cost to root on port
};

// 交换机级别的元数据记录，记录当前交换机的交换机编号，已经他所认为的根节点编号、
// 到他所认为的根交换机的代价，以及到根交换机最近的端口
struct stp {
	u64 switch_id;

	// 节点认为的根节点
	u64 designated_root;		// switch root (it believes)

	// 到根节点的路径开销，这里每一个网段的开销都是1，所以
	int root_path_cost;			// cost of path to root

	// 根端口指针
	stp_port_t *root_port;		// lowest cost port to root

	long long int last_tick;	// switch timers

	stp_timer_t hello_timer;	// hello timer

	// ports
	int nports;
	//参与stp协议的端口，这些端口连接交换机
	stp_port_t ports[STP_MAX_PORTS];

	pthread_mutex_t lock;
	pthread_t timer_thread;
};

void stp_init(struct list_head *iface_list);
void stp_destroy();

void stp_port_handle_packet(stp_port_t *, char *packet, int pkt_len);

#endif
